package de.rosstauscher.jculfw.fs20;


/**********************************************************
 * Some utility methods for FS20
 * @author Rossi java@rosstauscher.de
 *********************************************************/

public class FS20Util {
	
	/**********************************************************
	 * Converts a given housecode in ELV notation into the HEX
	 * notation understood by CUL.
	 * @param elvHouseCode to convert
	 * @return the corresponding HEX code.
	 *********************************************************/
	
	public static String elvToHex(String elvHouseCode) {
		elvHouseCode = elvHouseCode.trim();
		if (elvHouseCode.length() != 4 && elvHouseCode.length() != 8) {
			throw new IllegalArgumentException("Invalid elv house code: "+elvHouseCode+" must have length 4 or 8.");
		}
		long result = 0;
		for (int i = 0; i < elvHouseCode.length(); i++) {
			result = result << 2;
			int add = elvHouseCode.charAt(i) - '1';
			if (add > 3) {
				throw new IllegalArgumentException("Housecode must only contain '1' to '4'");
			}
			result += add;
		}
		return ensureLeadingZeros(Long.toHexString(result), elvHouseCode.length()/2).toUpperCase();
	}

	/**********************************************************
	 * Helper method to add leading zeros to bloat the given 
	 * string to the requested minimum length.
	 * @param hex string to extend.
	 * @param minimumTotalLength for the result.
	 * @return the result with leading zeros.
	 *********************************************************/
	
	private static String ensureLeadingZeros(String hex, int minimumTotalLength) {
		while (hex.length() < minimumTotalLength) {
			hex = "0" + hex;
		}
		return hex;
	}

	/**********************************************************
	 * Converts a given housecode in HEX notation into the ELV
	 * notation.
	 * @param hexHouseCode to convert (should be 2 or 4 long)
	 * @return the corresponding ELV code.
	 *********************************************************/
	
	public static String hexToElv(String hexHouseCode) {
		hexHouseCode = hexHouseCode.toLowerCase();
		String result = "";
		for (int j = 0; j < hexHouseCode.length(); j++) {
			int b = Integer.valueOf(hexHouseCode.substring(j, j+1), 16);
			for (int i = 0; i < 2; i++) {
				result += ((b & 0xC) >> 2) + 1;
				b = (b & 0x3) << 2;
			}
		}
		return result;
	}
	
	/**********************************************************
	 * Converts a number of seconds into a FS20 timer 
	 * specification value. This will return the code for 
	 * the specification that is nearest to the provided number
	 * of seconds.
	 * @param seconds the number of seconds for the command.
	 * @return the HEX code of the time specification.
	 *********************************************************/
	
	public String getTimeSpec(long seconds) {
		String result = "";
		LOOP: 
		for (int i = 0; i <= 12; i++) {
			for (int j = 0; j <= 15; j++) {
				long val = (long) (Math.pow(2, i) * j * 0.25);
				if (val >= seconds) {
					result = Integer.toHexString(i) + Integer.toHexString(j);
					break LOOP;
				}
			}
		}
		if (result.length() == 2) {
			throw new IllegalArgumentException(
					"Specified timeout too large, max is 15360 seconds");
		}
		return result;
	}	
	
}
